package com.wande.dataplatform.filecollection.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wande.common.core.exception.ServiceException;
import com.wande.common.mybatis.core.page.PageQuery;
import com.wande.common.mybatis.core.page.TableDataInfo;
import com.wande.dataplatform.filecollection.common.enums.FileCollectionErrorCode;
import com.wande.dataplatform.filecollection.common.utils.MinioUtils;
import com.wande.dataplatform.filecollection.domain.CollectionRule;
import com.wande.dataplatform.filecollection.domain.CollectionTask;
import com.wande.dataplatform.filecollection.domain.FileRecord;
import com.wande.dataplatform.filecollection.domain.MappingRule;
import com.wande.dataplatform.filecollection.domain.bo.FileRecordQuery;
import com.wande.dataplatform.filecollection.domain.vo.FileRecordVo;
import com.wande.dataplatform.filecollection.mapper.CollectionRuleMapper;
import com.wande.dataplatform.filecollection.mapper.CollectionTaskMapper;
import com.wande.dataplatform.filecollection.mapper.FileRecordMapper;
import com.wande.dataplatform.filecollection.mapper.MappingRuleMapper;
import com.wande.dataplatform.filecollection.parser.IFileParser;
import com.wande.dataplatform.filecollection.parser.ParserConfig;
import com.wande.dataplatform.filecollection.service.IFileParsingService;
import com.wande.dataplatform.filecollection.service.IFileRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 文件记录服务实现
 *
 * @author wande
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FileRecordServiceImpl implements IFileRecordService {

    private final FileRecordMapper fileRecordMapper;
    private final CollectionTaskMapper collectionTaskMapper;
    private final CollectionRuleMapper collectionRuleMapper;
    private final MappingRuleMapper mappingRuleMapper;
    private final MinioUtils minioUtils;
    private final IFileParsingService fileParsingService;

    @Override
    public TableDataInfo<FileRecordVo> listFileRecords(FileRecordQuery query) {
        LambdaQueryWrapper<FileRecord> wrapper = buildQueryWrapper(query);
        Page<FileRecordVo> page = fileRecordMapper.selectVoPage(query.build(), wrapper);
        return TableDataInfo.build(page);
    }

    @Override
    public FileRecordVo getFileRecordDetail(Long id) {
        FileRecordVo fileRecord = fileRecordMapper.selectVoById(id);
        if (fileRecord == null) {
            throw new ServiceException(FileCollectionErrorCode.FILE_RECORD_NOT_FOUND.getMessage());
        }

        // 获取关联的任务和规则信息
        CollectionTask task = collectionTaskMapper.selectById(fileRecord.getTaskId());
        if (task != null) {
            fileRecord.setTaskCode(task.getTaskCode());
            CollectionRule rule = collectionRuleMapper.selectById(task.getRuleId());
            if (rule != null) {
                fileRecord.setRuleName(rule.getRuleName());
            }
        }

        return fileRecord;
    }

    @Override
    public Map<String, Object> previewFileData(Long id, Integer limit) {
        FileRecord fileRecord = fileRecordMapper.selectById(id);
        if (fileRecord == null) {
            throw new ServiceException(FileCollectionErrorCode.FILE_RECORD_NOT_FOUND.getMessage());
        }

        if (StrUtil.isBlank(fileRecord.getOssPath())) {
            throw new ServiceException(FileCollectionErrorCode.FILE_NOT_FOUND.getMessage());
        }

        try {
            // 从MinIO下载文件
            InputStream inputStream = minioUtils.downloadFile(fileRecord.getOssPath());

            // 获取解析器配置
            CollectionTask task = collectionTaskMapper.selectById(fileRecord.getTaskId());
            CollectionRule rule = collectionRuleMapper.selectById(task.getRuleId());
            MappingRule mappingRule = mappingRuleMapper.selectById(rule.getMappingRuleId());

            // 解析文件获取预览数据
            IFileParser parser = fileParsingService.getParser(fileRecord.getFileType());
            ParserConfig parserConfig = ParserConfig.fromJson(mappingRule.getParserConfig());

            List<Map<String, Object>> previewData = new ArrayList<>();
            Iterator<Map<String, Object>> iterator = parser.parse(inputStream, parserConfig);

            int count = 0;
            int maxLimit = limit != null ? limit : 100;
            while (iterator.hasNext() && count < maxLimit) {
                previewData.add(iterator.next());
                count++;
            }

            Map<String, Object> result = new HashMap<>();
            result.put("fileName", fileRecord.getFileName());
            result.put("fileType", fileRecord.getFileType());
            result.put("totalRecords", fileRecord.getParsedRecords());
            result.put("previewRecords", previewData.size());
            result.put("data", previewData);

            return result;
        } catch (Exception e) {
            log.error("预览文件数据失败: {}", e.getMessage(), e);
            throw new ServiceException(FileCollectionErrorCode.FILE_PREVIEW_FAILED.getMessage());
        }
    }

    @Override
    public String downloadFile(Long id) {
        FileRecord fileRecord = fileRecordMapper.selectById(id);
        if (fileRecord == null) {
            throw new ServiceException(FileCollectionErrorCode.FILE_RECORD_NOT_FOUND.getMessage());
        }

        if (StrUtil.isBlank(fileRecord.getOssPath())) {
            throw new ServiceException(FileCollectionErrorCode.FILE_NOT_FOUND.getMessage());
        }

        try {
            // 生成预签名下载URL(有效期1小时)
            return minioUtils.getFileUrl(fileRecord.getOssPath(), 3600);
        } catch (Exception e) {
            log.error("生成文件下载URL失败: {}", e.getMessage(), e);
            throw new ServiceException(FileCollectionErrorCode.FILE_DOWNLOAD_FAILED.getMessage());
        }
    }

    @Override
    public Map<String, Object> getFileStatistics(FileRecordQuery query) {
        LambdaQueryWrapper<FileRecord> wrapper = buildQueryWrapper(query);

        // 总文件数
        Long totalFiles = fileRecordMapper.selectCount(wrapper);

        // 按状态统计
        Map<String, Long> statusStats = fileRecordMapper.selectList(wrapper)
            .stream()
            .collect(Collectors.groupingBy(FileRecord::getStatus, Collectors.counting()));

        // 按文件类型统计
        Map<String, Long> typeStats = fileRecordMapper.selectList(wrapper)
            .stream()
            .collect(Collectors.groupingBy(FileRecord::getFileType, Collectors.counting()));

        // 总记录数统计
        Long totalParsedRecords = fileRecordMapper.selectList(wrapper)
            .stream()
            .mapToLong(f -> f.getParsedRecords() != null ? f.getParsedRecords() : 0L)
            .sum();

        Long totalLoadedRecords = fileRecordMapper.selectList(wrapper)
            .stream()
            .mapToLong(f -> f.getLoadedRecords() != null ? f.getLoadedRecords() : 0L)
            .sum();

        // 文件大小统计
        Long totalFileSize = fileRecordMapper.selectList(wrapper)
            .stream()
            .mapToLong(f -> f.getFileSize() != null ? f.getFileSize() : 0L)
            .sum();

        Map<String, Object> statistics = new HashMap<>();
        statistics.put("totalFiles", totalFiles);
        statistics.put("statusStats", statusStats);
        statistics.put("typeStats", typeStats);
        statistics.put("totalParsedRecords", totalParsedRecords);
        statistics.put("totalLoadedRecords", totalLoadedRecords);
        statistics.put("totalFileSize", totalFileSize);

        return statistics;
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<FileRecord> buildQueryWrapper(FileRecordQuery query) {
        LambdaQueryWrapper<FileRecord> wrapper = Wrappers.lambdaQuery();

        wrapper.eq(query.getTaskId() != null, FileRecord::getTaskId, query.getTaskId())
            .like(StrUtil.isNotBlank(query.getFileName()), FileRecord::getFileName, query.getFileName())
            .eq(StrUtil.isNotBlank(query.getFileType()), FileRecord::getFileType, query.getFileType())
            .eq(StrUtil.isNotBlank(query.getStatus()), FileRecord::getStatus, query.getStatus())
            .ge(query.getStartTime() != null, FileRecord::getCreateTime, query.getStartTime())
            .le(query.getEndTime() != null, FileRecord::getCreateTime, query.getEndTime());

        // 如果指定了规则ID,需要通过任务关联查询
        if (query.getRuleId() != null) {
            List<Long> taskIds = collectionTaskMapper.selectList(
                Wrappers.lambdaQuery(CollectionTask.class)
                    .eq(CollectionTask::getRuleId, query.getRuleId())
            ).stream().map(CollectionTask::getId).collect(Collectors.toList());

            if (!taskIds.isEmpty()) {
                wrapper.in(FileRecord::getTaskId, taskIds);
            } else {
                // 如果没有找到任务,返回空结果
                wrapper.eq(FileRecord::getId, -1L);
            }
        }

        wrapper.orderByDesc(FileRecord::getCreateTime);

        return wrapper;
    }
}
